﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Display;
using System.Data;

namespace MidTermWorkWPF
{
    /// <summary>
    /// AttributeTableWindow.xaml 的交互逻辑
    /// </summary>
    public partial class AttributeTableWindow : Window
    {
        IFeatureLayer selectedLayer;
        IMap m_map;
        IActiveView m_activeView = null;
        string selectedFeatureID = null;
        string strOBJECTID = null;

        #region 各种辅助函数
        // 获取属性表,创建datatable并返回
        private DataTable CreateDataTableFromArcTable(ITable table)
        {
            DataTable dataTable = new DataTable();

            try
            {
                // 获取字段集合
                IFields fields = table.Fields;

                // 添加列
                for (int i = 0; i < fields.FieldCount; i++)
                {
                    DataColumn column = new DataColumn(fields.Field[i].Name);
                    dataTable.Columns.Add(column);
                }

                // 添加数据行
                ICursor cursor = table.Search(null, true);
                IRow row = cursor.NextRow();
                while (row != null)
                {
                    DataRow dataRow = dataTable.NewRow();
                    for (int i = 0; i < fields.FieldCount; i++)
                    {
                        dataRow[i] = row.get_Value(i);
                    }
                    dataTable.Rows.Add(dataRow);

                    row = cursor.NextRow();
                }
            }
            catch (Exception ex)
            {
                // 处理异常
                MessageBox.Show(ex.Message);
            }

            return dataTable;
        }

        //获取选择的要素
        private IFeature GetCurrentFeature()
        {
            try
            {
                // 获取selectedFeatureID
                var selectedRow = ForAttributeTable.SelectedItem as DataRowView;
                selectedFeatureID = selectedRow.Row[0].ToString();

                IFeatureClass featureClass = ((IFeatureLayer)selectedLayer).FeatureClass;
                IFeature selectedFeature = featureClass.GetFeature(Convert.ToInt32(selectedFeatureID));
                return selectedFeature;
            }
            catch (Exception)
            {
                return null;
            }
        }

        private ISymbol CreateSimpleSsymbol(esriGeometryType geometryType)
        {
            ISymbol symbol = null;
            switch (geometryType)
            {
                case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint:
                    ISimpleMarkerSymbol markerSymbol = new SimpleMarkerSymbolClass();
                    markerSymbol.Color = getRGB(255, 0, 0);
                    markerSymbol.Size = 8;
                    symbol = markerSymbol as ISymbol;
                    break;
                case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:
                    ISimpleLineSymbol lineSymbol = new SimpleLineSymbolClass();
                    lineSymbol.Color = getRGB(255, 0, 0);
                    lineSymbol.Width = 4;
                    symbol = lineSymbol as ISymbol;
                    break;
                case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon:
                    ISimpleFillSymbol fillSymbol = new SimpleFillSymbolClass();
                    fillSymbol.Color = getRGB(255, 0, 0);
                    symbol = fillSymbol as ISymbol;
                    break;
                default:
                    break;
            }
            symbol.ROP2 = esriRasterOpCode.esriROPNotXOrPen;

            return symbol;
        }

        private IColor getRGB(int yourRed, int yourGreen, int yourBlue)
        {
            IRgbColor pRGB;
            pRGB = new RgbColorClass();
            pRGB.Red = yourRed;
            pRGB.Green = yourGreen;
            pRGB.Blue = yourBlue;
            pRGB.UseWindowsDithering = true;
            return pRGB;
        }

        private void DrawSymbol(ISymbol symbol, IGeometry geometry)
        {
            m_map.ClearSelection();
            m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, m_activeView.Extent);
            IScreenDisplay pDisplay = m_activeView.ScreenDisplay;

            pDisplay.StartDrawing(0, (short)esriScreenCache.esriNoScreenCache);
            pDisplay.SetSymbol(symbol);
            for (int i = 0; i < 10; i++)
            {
                switch (geometry.GeometryType)
                {
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPoint:
                        pDisplay.DrawPoint(geometry);
                        break;
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryMultipoint:
                        pDisplay.DrawMultipoint(geometry);
                        break;
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolyline:
                        pDisplay.DrawPolyline(geometry);
                        break;
                    case ESRI.ArcGIS.Geometry.esriGeometryType.esriGeometryPolygon:
                        pDisplay.DrawPolygon(geometry);
                        break;
                    default:
                        break;
                }
                System.Threading.Thread.Sleep(100);
            }
            //m_mapControl.FlashShape(geometry, 5, 300, symbol);
            pDisplay.FinishDrawing();
        }

        private IEnvelope GetLayerSelectedFeaturesEnvelope(IFeatureLayer pFeatLyr)
        {
            IEnvelope layerEnvelope = null;
            IFeatureClass pFeatCls = pFeatLyr.FeatureClass;
            IFeatureSelection selectLayer = pFeatLyr as IFeatureSelection;
            ISelectionSet selectionSet = selectLayer.SelectionSet;
            IEnumIDs enumIDs = selectionSet.IDs;
            IFeature feature;
            int i = 1;
            int iD = enumIDs.Next();
            while (iD != -1) //-1 is reutned after the last valid ID has been reached        
            {
                feature = pFeatCls.GetFeature(iD);
                IEnvelope envelope = feature.ShapeCopy.Envelope;
                if (i == 1)
                    layerEnvelope = envelope;
                else
                {
                    layerEnvelope.Union(envelope);
                }
                i++;
                iD = enumIDs.Next();
            }
            return layerEnvelope;
        }

        private void SelectFeatures(List<string> oidList)
        {
            IFeatureClass featureClass = selectedLayer.FeatureClass;
            string strID = string.Empty;
            string[] IDs = oidList.ToArray();
            for (int i = 0; i < IDs.Length; i++)
            {
                strID = IDs[i];
                IFeature selectedFeature = featureClass.GetFeature(Convert.ToInt32(strID));
                m_map.SelectFeature(selectedLayer, selectedFeature);
            }
            //m_activeView.PartialRefresh((esriViewDrawPhase)6, null, m_activeView.Extent);
        }

        private void FindOIDField()
        {
            if (selectedLayer == null) return;
            IFields fields = selectedLayer.FeatureClass.Fields;
            IField field;
            for (int i = 0; i < fields.FieldCount; i++)
            {
                field = fields.get_Field(i);
                if (field.Type == esriFieldType.esriFieldTypeOID)
                {
                    strOBJECTID = field.Name;
                    break;
                }
            }
        }

        private void DeleteSelectedFeatures()
        {
            IFeatureClass pFeatCls = selectedLayer.FeatureClass;
            IFeatureSelection selectLayer = selectedLayer as IFeatureSelection;
            ISelectionSet selectionSet = selectLayer.SelectionSet;
            IEnumIDs enumIDs = selectionSet.IDs;
            IFeature feature;
            int iD = enumIDs.Next();
            while (iD != -1) //-1 is reutned after the last valid ID has been reached        
            {
                feature = pFeatCls.GetFeature(iD);
                feature.Delete();
                iD = enumIDs.Next();
            }
        }

        #endregion

        //构造函数
        public AttributeTableWindow(ILayer m_Layer, IMap map)
        {
            InitializeComponent();
            selectedLayer = m_Layer as IFeatureLayer;
            m_map = map;
            m_activeView = m_map as IActiveView;
        }

        // 窗口加载
        private void AttributeTable_Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 获取属性表
            ITable table = selectedLayer as ITable;
            if (table != null)
            {
                // 将属性表数据转换为DataTable
                DataTable dataTable = CreateDataTableFromArcTable(table);

                // 将DataTable绑定到WPF的DataGrid控件
                ForAttributeTable.ItemsSource = dataTable.DefaultView;
            }
            FindOIDField();
            ForSelectedFeaturesNum.Content = "选择记录数：0";
            ForAllFeaturesNum.Content = "总记录数：" + selectedLayer.FeatureClass.FeatureCount(null).ToString();
        }

        //当用户点击的要素变化时，获取用户选择要素的行号,进而获取要素的ID
        private void ForAttributeTable_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            m_map.ClearSelection();
            m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, m_activeView.Extent);

            var selectedItems = ForAttributeTable.SelectedItems;
            if (selectedItems == null) return;

            string strOID = string.Empty;
            List<string> OIDList = new List<string>();

            foreach (var selectedItem in selectedItems)
            {
                DataRowView dataRowView = selectedItem as DataRowView;
                if (dataRowView != null)
                {
                    strOID = dataRowView[strOBJECTID].ToString();
                    OIDList.Add(strOID);
                }
            }

            SelectFeatures(OIDList);
            ForSelectedFeaturesNum.Content = "选择记录数：" + OIDList.Count.ToString();
            //ForAllFeaturesNum.Content = "总记录数：" + selectedLayer.FeatureClass.FeatureCount(null).ToString();
        }

        // 闪烁选中要素
        private void BlinkFeature_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                IFeature selectedFeature = GetCurrentFeature();
                IGeometry geometry = selectedFeature.Shape;

                m_map.ClearSelection();
                m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, m_activeView.Extent);
                m_map.SelectFeature(selectedLayer, selectedFeature); 

                MoveToTheFeature_Click(sender, e);

                ISymbol symbol = CreateSimpleSsymbol(geometry.GeometryType);
                if (symbol == null) return;
                DrawSymbol(symbol, geometry);

                m_map.SelectFeature(selectedLayer, selectedFeature);
                m_activeView.PartialRefresh((esriViewDrawPhase)6, null, m_activeView.Extent);

                //m_map.SelectFeature(selectedLayer, selectedFeature);
                //m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, m_activeView.Extent);
                //m_activeView.ScreenDisplay.UpdateWindow();
            }
            catch (Exception)
            {
                return;
            }
        }

        // 缩放到选中要素
        private void ZoomToTheFeature_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                IEnvelope pEnvelope = new EnvelopeClass();
                IFeature selectedFeature = GetCurrentFeature();
                m_map.SelectFeature(selectedLayer, selectedFeature);
                if (selectedLayer.FeatureClass.ShapeType == esriGeometryType.esriGeometryPoint)
                {
                    pEnvelope = m_activeView.Extent;
                    pEnvelope.Height = pEnvelope.Height / 2;
                    pEnvelope.Width = pEnvelope.Width / 2;
                    pEnvelope.CenterAt(selectedFeature.ShapeCopy as IPoint);
                }
                else
                {
                    pEnvelope = selectedFeature.Extent;
                }

                m_activeView.Extent = pEnvelope;
                //m_activeView.Refresh();

                m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, m_activeView.Extent);
                m_map.ClearSelection();
                m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, m_activeView.Extent);
                m_map.SelectFeature(selectedLayer, selectedFeature); 
            }
            catch (Exception)
            {
                return;
            }
        }

        // 平移到选中要素
        private void MoveToTheFeature_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                IFeature selectedFeature = GetCurrentFeature();
                IGeometry geometry = selectedFeature.Shape;
                IPoint pCenterPoint = new PointClass();
                //double x = (geometry.Envelope.LowerLeft.X + geometry.Envelope.UpperRight.X) / 2;
                //double y = (geometry.Envelope.LowerLeft.Y + geometry.Envelope.UpperRight.Y) / 2;

                double x = geometry.Envelope.LowerLeft.X + geometry.Envelope.Width / 2;
                double y = geometry.Envelope.LowerLeft.Y + geometry.Envelope.Height / 2;
                pCenterPoint.PutCoords(x, y);

                IDisplayTransformation pDisplayTransform = m_activeView.ScreenDisplay.DisplayTransformation;
                IEnvelope pEnvelope = pDisplayTransform.VisibleBounds;
                pEnvelope.CenterAt(pCenterPoint);
                pDisplayTransform.VisibleBounds = pEnvelope;

                //m_map.SelectFeature(currentLayer, selectedFeature);

                //m_activeView.PartialRefresh((esriViewDrawPhase)6, null, m_activeView.Extent);
                m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, m_activeView.Extent);

                m_activeView.ScreenDisplay.UpdateWindow();

                m_map.ClearSelection();
                m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, m_activeView.Extent);
                m_map.SelectFeature(selectedLayer, selectedFeature); 

                //ISymbol symbol = CreateSimpleSsymbol(geometry.GeometryType);
                //if (symbol == null) return;
                //DrawSymbol(symbol, geometry);
            }
            catch (Exception)
            {
                return;
            }
        }

        // 缩放到图层
        private void ZoomToTheLayer_Click(object sender, RoutedEventArgs e)
        {
            m_activeView.Extent = ((IGeoDataset)selectedLayer).Extent;
            m_activeView.ScreenDisplay.UpdateWindow();
            m_activeView.PartialRefresh((esriViewDrawPhase)6, null, m_activeView.Extent);
        }

        // 缩放到所有选择要素
        private void ZoomtoAllSelectedFeature_Click(object sender, RoutedEventArgs e)
        {
            IEnvelope wholeEnvelope = GetLayerSelectedFeaturesEnvelope(selectedLayer);
            if (wholeEnvelope == null) return;

            m_activeView.Extent = wholeEnvelope;
            //m_activeView.ScreenDisplay.UpdateWindow();
            m_activeView.PartialRefresh((esriViewDrawPhase)6, null, m_activeView.Extent);
        }

        private void ClearAllSelectedFeature_Click(object sender, RoutedEventArgs e)
        {
            m_map.ClearSelection();
            //m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, m_activeView.Extent);
            ForAttributeTable.UnselectAll();
        }

        private void DelectedAllSelectedFeature_Click(object sender, RoutedEventArgs e)
        {
            DeleteSelectedFeatures();
            m_activeView.Refresh();
        }

    }
}
